// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StringValueValidator.cs" company="">
//   
// </copyright>
// <summary>
//   The string value validator.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Skymate.Runtime.Validation
{
    using System;
    using System.Globalization;
    using System.Text.RegularExpressions;

    using Skymate.Extensions;

    /// <summary>
    ///     The string value validator.
    /// </summary>
    [Serializable]
    [Validator("STRING")]
    public class StringValueValidator : ValueValidatorBase
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="StringValueValidator" /> class.
        /// </summary>
        public StringValueValidator()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="StringValueValidator"/> class.
        /// </summary>
        /// <param name="minLength">
        /// The min length.
        /// </param>
        /// <param name="maxLength">
        /// The max length.
        /// </param>
        /// <param name="regularExpression">
        /// The regular expression.
        /// </param>
        /// <param name="allowNull">
        /// The allow null.
        /// </param>
        public StringValueValidator(
            int minLength = 0, 
            int maxLength = 0, 
            string regularExpression = null, 
            bool allowNull = false)
        {
            this.MinLength = minLength;
            this.MaxLength = maxLength;
            this.RegularExpression = regularExpression;
            this.AllowNull = allowNull;
        }

        /// <summary>
        ///     Gets or sets a value indicating whether allow null.
        /// </summary>
        public bool AllowNull
        {
            get
            {
                return (this["AllowNull"] ?? "false").To<bool>();
            }

            set
            {
                this["AllowNull"] = value.ToString().ToLower(CultureInfo.InvariantCulture);
            }
        }

        /// <summary>
        ///     Gets or sets the min length.
        /// </summary>
        public int MinLength
        {
            get
            {
                return (this["MinLength"] ?? "0").To<int>();
            }

            set
            {
                this["MinLength"] = value;
            }
        }

        /// <summary>
        ///     Gets or sets the max length.
        /// </summary>
        public int MaxLength
        {
            get
            {
                return (this["MaxLength"] ?? "0").To<int>();
            }

            set
            {
                this["MaxLength"] = value;
            }
        }

        /// <summary>
        ///     Gets or sets the regular expression.
        /// </summary>
        public string RegularExpression
        {
            get
            {
                return this["RegularExpression"] as string;
            }

            set
            {
                this["RegularExpression"] = value;
            }
        }

        /// <summary>
        /// The is valid.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public override bool IsValid(object value)
        {
            if (value == null)
            {
                return this.AllowNull;
            }

            if (!(value is string))
            {
                return false;
            }

            var strValue = value as string;

            if (this.MinLength > 0 && strValue.Length < this.MinLength)
            {
                return false;
            }

            if (this.MaxLength > 0 && strValue.Length > this.MaxLength)
            {
                return false;
            }

            if (!this.RegularExpression.IsNullOrEmpty())
            {
                return Regex.IsMatch(strValue, this.RegularExpression);
            }

            return true;
        }
    }
}